#ifndef XL_UPLOADER_xDOCUMENT_H
#define XL_UPLOADER_xDOCUMENT_H

#include <vector>
#include <map>
#include "Observable.h"
#include "FileInfo.h"


class CxDocument : public CObserableT<CxDocument>
{
public:
	typedef size_t                   INDEX;
	static const size_t              INVALID_INDEX = 0xFFFFFFFF;
	enum EVENT : CObserableT<CxDocument>::EVT {
		EVT_ADD,       // param is &id
		EVT_UPDATE,    // param is &id
		EVT_REMOVE,    // param is &FileInfo which removed
		EVT_CLEAR,     // param is NULL
		EVT_NUM,
	};


private:
	typedef std::map<
	                 tstring, 
	                 FileInfo::ID, 
	                 func_tstring_iless<tstring>
	                >                FileNameIdMap;
	typedef std::vector<FileInfo>    FileContainer;
	FileContainer                    m_files;
	FileNameIdMap                    m_nameIdMap;
	size_t                           m_lastID;
	UINT                             m_err;

	CRITICAL_SECTION                 m_cs;

	FileInfo& _GetFileByIndex(INDEX index);

public:
	CxDocument();
	~CxDocument();


	UINT getLastError();

	//////////////////////////////////////////////////////////////////////////
	// set / update
	/**
	 * if pathname already exists, return INVALID_ID and getLastError() will return ERROR_ALREADY_EXISTS
	 */
	FileInfo::ID addFile(const TCHAR *pathname);
	void remove(FileInfo::ID id);
	void clear();

	void setFileUploadProgress(FileInfo::ID id, size_t progress);
	void setFileUploadResult(FileInfo::ID id, FileInfo::UPLOAD_STATUS status, const std::string &result);

	/**
	 * important: after this call, if not INVALID_INDEX returned, the **.status** of related FI has 
	 * already been set to FileInfo::UPLOAD_ING, and the .progress is set to zero.
	 */
	FileInfo::ID getUpdateId();

	//////////////////////////////////////////////////////////////////////////
	// get
	INDEX getIndexById(FileInfo::ID id) const;

	size_t getFileCount() const;
	const FileInfo& getFileByIndex(INDEX index) const;

	size_t getFileCountByStatus(FileInfo::UPLOAD_STATUS) const;
	INDEX getFirstIndexByStatus(FileInfo::UPLOAD_STATUS) const;


};

#endif
